package org.example.ag_notes.service;

import jakarta.security.auth.message.AuthException;
import org.example.ag_notes.dto.article.TreeNodeDto;
import org.example.ag_notes.entity.Article;
import org.example.ag_notes.entity.TreeNode;
import org.example.ag_notes.entity.User;
import org.example.ag_notes.entity.enums.NodeType;
import org.example.ag_notes.exception.AuthenticationException;
import org.example.ag_notes.exception.BusinessException;
import org.example.ag_notes.repository.ArticleRepository;
import org.example.ag_notes.repository.TreeNodeRepository;
import org.example.ag_notes.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class TreeNodeService extends BaseService {

    private final TreeNodeRepository nodeRepo;
    private final ArticleRepository articleRepo;
    private final AuthService authService;
    private final UserRepository userRepo;

    @Autowired
    public TreeNodeService(TreeNodeRepository nodeRepo, ArticleRepository articleRepo, AuthService authService, UserRepository userRepo) {
        this.nodeRepo = nodeRepo;
        this.articleRepo = articleRepo;
        this.authService = authService;
        this.userRepo = userRepo;
    }


    /**
     * 添加树节点（只允许文件夹类型）
     */
    public TreeNodeDto addNode(TreeNodeDto dto, String token) {
        try {
            User user = validateAndGetUser(token);

            TreeNode parent = null;
            if (dto.getParentId() != null) {
                parent = nodeRepo.findById(dto.getParentId())
                        .orElseThrow(() -> new BusinessException("父节点不存在"));
            }

            if (dto.getType() != NodeType.DIRECTORY && dto.getType() != NodeType.ARTICLE) {
                throw new BusinessException("类型错误");
            }

            // 2. 构造 TreeNode 实体
            TreeNode node = new TreeNode();
            node.setLabel(dto.getLabel());
            node.setType(dto.getType()); // 设置为 DIRECTORY 类型
            node.setParentNode(parent);
            node.setUser(user);

            // 3. 保存并转换为 DTO 返回
            TreeNode saved = nodeRepo.save(node);
            return convertToDto(saved);

        } catch (BusinessException e) {
            System.err.println("业务异常：" + e.getMessage());
            throw e;

        } catch (Exception e) {
            System.err.println("系统异常：" + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }



    /**
     * 获取用户的节点树结构
     * @param accessToken 用户访问令牌
     * @return 用户的节点树结构
     */
    public List<TreeNodeDto> listUserNodes(String accessToken) {
        User user = validateAndGetUser(accessToken);

        // 3. 查询用户的所有节点
        List<TreeNode> nodes = nodeRepo.findByUser(user);

        // 4. 转换为DTO并构建树形结构
        return buildTree(nodes);
    }

    /**
     * 构建树形结构
     */
    private List<TreeNodeDto> buildTree(List<TreeNode> nodes) {
        // 转换为DTO列表
        List<TreeNodeDto> dtos = nodes.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());

        // 建立ID到节点的映射
        Map<Integer, TreeNodeDto> dtoMap = new HashMap<>();
        dtos.forEach(dto -> dtoMap.put(dto.getId(), dto));

        // 构建树形结构
        List<TreeNodeDto> tree = new ArrayList<>();
        for (TreeNodeDto dto : dtos) {
            if (dto.getParentId() == null) {
                tree.add(dto);
            } else {
                TreeNodeDto parent = dtoMap.get(dto.getParentId());
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(dto);
                }
            }
        }

        return tree;
    }

    /**
     * 将TreeNode实体转换为TreeNodeDto
     */
    private TreeNodeDto convertToDto(TreeNode node) {
        TreeNodeDto dto = new TreeNodeDto();
        dto.setId(node.getId());
        dto.setLabel(node.getLabel());
        dto.setType(node.getType());
        dto.setParentId(node.getParentNode() != null ? node.getParentNode().getId() : null);
        dto.setArticleId(node.getArticle() != null ? node.getArticle().getId() : null);
        dto.setChildren(new ArrayList<>());
        return dto;
    }

    /**
     *
     * @param nodeDto
     * @return 返回更新成功的节点信息
     * 更新节点的信息，比如titile或articleid等
     */
    //TODO 更新节点方法
    public TreeNodeDto updateNode(TreeNodeDto nodeDto , String token){
        User user = validateAndGetUser(token);

        // 3. 查找要更新的节点
        TreeNode existingNode = nodeRepo.findById(nodeDto.getId())
                .orElseThrow(() -> new BusinessException("节点不存在"));

        // 4. 验证该节点是否属于当前用户
        if (!existingNode.getUser().getId().equals(user.getId())) {
            throw new AuthenticationException("无权限修改该节点");
        }

        // 5. 更新节点属性
        if (nodeDto.getLabel() != null) {
            existingNode.setLabel(nodeDto.getLabel());
        }

        System.err.println(nodeDto);
        if (nodeDto.getArticleId() != null) {
            // 绑定文章
            System.err.println(nodeDto.getArticleId());
            Article article = articleRepo.findById(nodeDto.getArticleId())
                    .orElseThrow(() -> new BusinessException("文章不存在"));
            existingNode.setArticle(article);
        }
        System.err.println("11");
        // 6. 保存更新后的节点
        TreeNode updatedNode = nodeRepo.save(existingNode);

        // 7. 构建 DTO 返回
        return TreeNodeDto.fromEntity(updatedNode);
    }

    /**
     * 删除树节点（递归删除子节点）
     * @param nodeId 节点ID
     * @param token 用户身份验证令牌
     */
    public void deleteNode(Integer nodeId, String token) {
        User user = validateAndGetUser(token);

        // 查询节点
        TreeNode node = nodeRepo.findById(nodeId)
                .orElseThrow(() -> new BusinessException("节点不存在"));

        // 验证权限
        if (!node.getUser().getId().equals(user.getId())) {
            throw new AuthenticationException("无权限删除该节点");
        }

        // 执行递归删除
        deleteRecursively(node);
    }


    /**
     * 递归删除节点及其子节点
     */
    private void deleteRecursively(TreeNode node) {
        List<TreeNode> children = nodeRepo.findByParentNode(node);
        for (TreeNode child : children) {
            deleteRecursively(child); // 递归删除子节点
        }

        // 清除文章关联（如果是文章节点）
        if (node.getType() == NodeType.ARTICLE && node.getArticle() != null) {
            node.setArticle(null);
        }

        nodeRepo.delete(node);
    }

}